package com.ohos.connent.modelcloud.biz.modular.pro.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ohos.connent.modelcloud.auth.core.util.StpLoginUserUtil;
import com.ohos.connent.modelcloud.biz.modular.pro.entity.BizProCategory;
import com.ohos.connent.modelcloud.biz.modular.pro.mapper.BizProCategoryMapper;
import com.ohos.connent.modelcloud.biz.modular.pro.param.*;
import com.ohos.connent.modelcloud.biz.modular.pro.result.BizProCategoryDetailResult;
import com.ohos.connent.modelcloud.biz.modular.pro.service.BizProCategoryDictService;
import com.ohos.connent.modelcloud.biz.modular.pro.service.BizProCategoryService;
import com.ohos.connent.modelcloud.biz.modular.pro.util.SequenceGeneratorUtil;
import com.ohos.connent.modelcloud.common.exception.CommonException;
import com.ohos.connent.modelcloud.common.util.CommonResponseUtil;
import com.ohos.connent.modelcloud.dev.api.DevFileApi;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;


/**
 * 品类服务实现类
 *
 * @Author: ChenJiaHao
 * @Date: 2024/5/31 15:26
 * @Description:
 */
@Service
public class BizProCategoryServiceImpl extends ServiceImpl<BizProCategoryMapper, BizProCategory> implements BizProCategoryService {

    // 图片缓存Map对象
    private static final Map<String, Map<String, String>> ICON_CACHE_MAP = new ConcurrentHashMap<>();

    @Resource
    DevFileApi devFileApi;
    @Resource
    private BizProCategoryDictService bizProCategoryDictService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String add(BizProCategoryAddParam bizProCategoryAddParam) {
        BizProCategory bizProCategory = BeanUtil.copyProperties(bizProCategoryAddParam, BizProCategory.class);
        bizProCategory.setId(IdWorker.getIdStr()).setDictId(addDict(bizProCategoryAddParam)).setCategoryId(nextCategoryId());
        bizProCategory.setCreateUser(StpLoginUserUtil.getLoginUser().getName());
        String iconId = bizProCategoryAddParam.getIconId();
        if (ObjectUtil.isNotEmpty(iconId)) {
            bizProCategory.setIconId(iconId).setIconBase64(iconBase64(iconId)).setIconName(iconName(iconId));
        }
        this.save(bizProCategory);
        return bizProCategory.getId();
    }



    private String addDict(BizProCategoryAddParam bizProCategoryAddParam) {
        BizProCategoryDictAddParam dictAddParam = new BizProCategoryDictAddParam();
        dictAddParam.setName(bizProCategoryAddParam.getChineseName());
        dictAddParam.setParentId(bizProCategoryAddParam.getParentId());
        return bizProCategoryDictService.add(dictAddParam);
    }

    private String nextCategoryId() {
        QueryWrapper<BizProCategory> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().select(BizProCategory::getCategoryId).orderByDesc(BizProCategory::getCategoryId).last(" LIMIT 1 ");
        BizProCategory maxProCategory = this.getOne(queryWrapper);
        return SequenceGeneratorUtil.getNextSequence(ObjectUtil.isEmpty(maxProCategory) ? null : maxProCategory.getCategoryId());
    }

    private String iconBase64(String iconId) {
        if (!ICON_CACHE_MAP.containsKey(iconId)) {
            throw new CommonException("图片不存在或已过期");
        }
        return ICON_CACHE_MAP.get(iconId).get("iconBase64");
    }

    private String iconName(String iconId) {
        return ICON_CACHE_MAP.get(iconId).get("iconName");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String edit(BizProCategoryEditParam bizProfileEditParam) {
        BizProCategory bizProCategory = queryEntity(bizProfileEditParam.getId());
        BeanUtil.copyProperties(bizProfileEditParam, bizProCategory);
        String iconId = bizProfileEditParam.getIconId();
        if (ObjectUtil.isNotEmpty(iconId)) {
            bizProCategory.setIconId(iconId).setIconBase64(iconBase64(iconId)).setIconName(iconName(iconId));
        }
        this.updateById(bizProCategory);
        return bizProCategory.getId();
    }

    @Override
    public BizProCategoryDetailResult detail(BizProCategoryIdParam bizProCategoryIdParam) {
        BizProCategory bizProCategory = queryEntity(bizProCategoryIdParam.getId());
        String fileName = devFileApi.getFileName(bizProCategory.getFileId());
        return BeanUtil.copyProperties(bizProCategory, BizProCategoryDetailResult.class).setProfileName(fileName).setCreateUserName(bizProCategory.getCreateUser());
    }

    @Override
    public BizProCategoryDetailResult detailByDictId(BizProCategoryDictIdParam bizProCategoryDictIdParam) {
        QueryWrapper<BizProCategory> queryWrapper = new QueryWrapper<>();
        BizProCategory bizProCategory = getOne(queryWrapper.lambda().eq(BizProCategory::getDictId, bizProCategoryDictIdParam.getId()));
        if (ObjectUtil.isEmpty(bizProCategory)) {
            return null;
        }
        String fileName = devFileApi.getFileName(bizProCategory.getFileId());
        return BeanUtil.copyProperties(bizProCategory, BizProCategoryDetailResult.class).setProfileName(fileName).setCreateUserName(bizProCategory.getCreateUser());
    }

    @Override
    public BizProCategory queryEntity(String id) {
        BizProCategory bizProCategory = this.getById(id);
        if (ObjectUtil.isEmpty(bizProCategory)) {
            throw new CommonException("品类不存在，id值为：{}", id);
        }
        return bizProCategory;
    }

    @Override
    public String getFileDownloadAuthUrlHUAWEI(BizProCategoryFileIdParam bizProCategoryFileIdParam) {
        String url = devFileApi.getFileDownloadAuthUrlHUAWEI(bizProCategoryFileIdParam.getFileId(), 3600L);
        if (ObjectUtil.isEmpty(url) || "没有相关文件".equals(url)) {
            throw new CommonException("无法获取文件下载路径");
        }
        return url;
    }


    @Override
    public void iconDownload(BizProCategoryIdParam bizProCategoryIdParam, HttpServletResponse response) throws IOException {
        String id = bizProCategoryIdParam.getId();
        BizProCategory bizProCategory = queryEntity(id);
        if (ObjectUtil.isEmpty(bizProCategory.getIconBase64())) {
            throw new CommonException("图片不存在");
        }
        try {
            String suffix = StrUtil.subAfter(bizProCategory.getIconName(), StrUtil.DOT, true);
            ImgUtil.write(ImgUtil.toImage(bizProCategory.getIconBase64()), suffix, response.getOutputStream());
        } catch (Exception e) {
            log.error(">>> 图片下载失败：", e);
            CommonResponseUtil.renderError(response, "图片下载失败");
        }
    }

    @Override
    public String geFileUploadIconId(MultipartFile file) {
        String iconId = getMD5(file);
        // 如果文件已经在缓存中，则不存储，直接返回Md5
        if (!ICON_CACHE_MAP.containsKey(iconId)) {
            checkAndStoreIcon(file, iconId);
        }
        return iconId;
    }

    private String getMD5(MultipartFile file) {
        String md5Hex;
        try {
            md5Hex = DigestUtils.md5Hex(file.getBytes());
        } catch (Exception e) {
            // 如果md5值获取失败则用id，确保逻辑往下走
            log.error(">>> 解析图片获取MD5值失败：", e);
            md5Hex = IdWorker.getIdStr();
        }
        return md5Hex;
    }

    private void checkAndStoreIcon(MultipartFile file, String iconId) {
        String originalFilename = file.getOriginalFilename();
        String suffix = ObjectUtil.isNotEmpty(originalFilename) ? StrUtil.subAfter(originalFilename, StrUtil.DOT, true) : null;
        if (ObjectUtil.isEmpty(suffix) || !isPic(Objects.requireNonNull(suffix))) {
            throw new CommonException("图片格式不符合要求");
        }
        if (NumberUtil.compare(100 * 1024, file.getSize()) == -1) {
            throw new CommonException("图片大小不符合要求，请上传大小不超过100KB的图片");
        }
        String iconBase64 = null;
        try {
            iconBase64 = ImgUtil.toBase64(ImgUtil.scale(ImgUtil.toImage(file.getBytes()), 400, 400, null), suffix);
        } catch (Exception e) {
            log.error(">>> 图片解析失败：", e);
        }
        if (ObjectUtil.isEmpty(iconBase64)) {
            throw new CommonException("图片解析失败");
        }
        Map<String, String> map = new HashMap<>();
        map.put("iconName", originalFilename);
        map.put("iconBase64", iconBase64);

        // 放到本地缓存中
        ICON_CACHE_MAP.put(iconId, map);
    }

    private static boolean isPic(String suffix) {
        String fileSuffix = suffix.toLowerCase();
        return ImgUtil.IMAGE_TYPE_GIF.equals(fileSuffix)
                || ImgUtil.IMAGE_TYPE_JPG.equals(fileSuffix)
                || ImgUtil.IMAGE_TYPE_JPEG.equals(fileSuffix)
                || ImgUtil.IMAGE_TYPE_BMP.equals(fileSuffix)
                || ImgUtil.IMAGE_TYPE_PNG.equals(fileSuffix)
                || ImgUtil.IMAGE_TYPE_PSD.equals(fileSuffix);
    }

}
